home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-07-03 | 7.2 KB | 225 lines | [TEXT/R*ch] |
- open
- Obj Fnlib Config Mixture Const Instruct Prim
- Opcodes Prim_opc Buffcode Labels Reloc
- ;
-
- prim_val lshift_ : int -> int -> int = 2 "shift_left";
- prim_val rshiftsig_ : int -> int -> int = 2 "shift_right_signed";
- prim_val rshiftuns_ : int -> int -> int = 2 "shift_right_unsigned";
-
-
- (* Generation of bytecode for .uo files *)
-
- fun checkAccessIndex n =
- if n <= maxint_byte then () else
- (msgIBlock 0;
- errPrompt "Too many local variables, unable to compile into bytecode";
- msgEOL();
- msgEBlock();
- raise Toplevel)
- ;
-
- fun out_bool_test tst =
- fn PTeq => out tst
- | PTnoteq => out (tst + 1)
- | PTlt => out (tst + 2)
- | PTgt => out (tst + 3)
- | PTle => out (tst + 4)
- | PTge => out (tst + 5)
- | _ => fatalError "out_bool_test"
- ;
-
- fun out_int_const i =
- if i >= minint_short andalso i <= maxint_short then
- let val ii1 = i+i+1 in
- if ii1 >= minint_byte andalso ii1 <= maxint_byte then
- (out CONSTBYTE; out (ii1))
- else if ii1 >= minint_short andalso ii1 <= maxint_short then
- (out CONSTSHORT; out_short (ii1))
- else
- (out GETGLOBAL; slot_for_literal(ATOMsc(INTscon i)))
- end
- else
- (out GETGLOBAL; slot_for_literal(ATOMsc(INTscon i)))
- ;
-
- fun out_tag (CONtag(t,_)) = out t
- | out_tag (EXNtag(name, stamp)) =
- slot_for_tag name stamp
- ;
-
- fun out_header (n, tag) =
- (
- out_tag tag;
- out (lshift_ n 2);
- out (rshiftuns_ n 6);
- out (rshiftuns_ n 14)
- );
-
- fun emit zams =
- case zams of
- [] => ()
- | Kquote(ATOMsc(INTscon i)) :: C =>
- (out_int_const i;
- emit C)
- | Kquote(ATOMsc(CHARscon c)) :: C =>
- (out_int_const (Char.ord c);
- emit C)
- | Kquote(BLOCKsc(tag, [])) :: C =>
- (case tag of
- CONtag(t,_) =>
- if t < 10 then out (ATOM0 + t) else (out ATOM; out t)
- | EXNtag(name, stamp) =>
- (out ATOM; slot_for_tag name stamp);
- emit C)
- | Kquote sc :: C =>
- (out GETGLOBAL; slot_for_literal sc;
- emit C)
- | Kget_global uid :: C =>
- (out GETGLOBAL;
- slot_for_get_global uid;
- emit C)
- | Kset_global uid :: C =>
- (out SETGLOBAL;
- slot_for_set_global uid;
- emit C)
- | Kaccess n :: C =>
- (checkAccessIndex n;
- if n < 6 then out(ACC0 + n) else (out ACCESS; out n);
- emit C)
- | Kendlet n :: Kendlet p :: C =>
- emit(Kendlet(n+p) :: C)
- | Kendlet 1 :: C =>
- (out ENDLET1; emit C)
- | Kendlet n :: C =>
- (checkAccessIndex n;
- out ENDLET; out n; emit C)
- | Kletrec1 lbl :: C =>
- (out LETREC1; out_label lbl; emit C)
- | Kmakeblock(tag,n) :: C =>
- (if n <= 0 then
- fatalError "emit : Kmakeblock"
- else if n < 5 then
- (out (MAKEBLOCK1 + n - 1);
- out_tag tag)
- else
- (out MAKEBLOCK;
- out_header(n, tag));
- emit C)
- | Klabel lbl :: C =>
- if lbl = Nolabel then fatalError "emit: undefined label" else
- (define_label lbl; emit C)
- | Kclosure lbl :: C =>
- (out CUR; out_label lbl; emit C)
- | Kpushtrap lbl :: C =>
- (out PUSHTRAP; out_label lbl; emit C)
- | Kbranch lbl :: C =>
- (out BRANCH; out_label lbl; emit C)
- | Kbranchif lbl :: C =>
- (out BRANCHIF; out_label lbl; emit C)
- | Kbranchifnot lbl :: C =>
- (out BRANCHIFNOT; out_label lbl; emit C)
- | Kstrictbranchif lbl :: C =>
- (out BRANCHIF; out_label lbl; emit C)
- | Kstrictbranchifnot lbl :: C =>
- (out BRANCHIFNOT; out_label lbl; emit C)
- | Kswitch lblvect :: C =>
- let val len = Array.length lblvect
- val () = out SWITCH;
- val () = out len;
- val orig = !out_position
- in
- for (fn i => out_label_with_orig orig (Array.sub(lblvect, i)))
- 0 (len-1);
- emit C
- end
- | Ktest(tst,lbl) :: C =>
- (case tst of
- Peq_test =>
- (out BRANCHIFEQ; out_label lbl)
- | Pnoteq_test =>
- (out BRANCHIFNEQ; out_label lbl)
- | Pint_test(PTnoteqimm i) =>
- (out PUSH; out PUSH; out_int_const i;
- out EQ; out POPBRANCHIFNOT; out_label lbl)
- | Pint_test x =>
- (out_bool_test BRANCHIFEQ x; out_label lbl)
- | Pfloat_test(PTnoteqimm f) =>
- (out PUSH; out PUSH; out GETGLOBAL;
- slot_for_literal (ATOMsc(REALscon f));
- out EQFLOAT; out POPBRANCHIFNOT; out_label lbl)
- | Pfloat_test x =>
- (out_bool_test EQFLOAT x; out BRANCHIF; out_label lbl)
- | Pstring_test(PTnoteqimm s) =>
- (out PUSH; out PUSH; out GETGLOBAL;
- slot_for_literal (ATOMsc(STRINGscon s));
- out EQSTRING; out POPBRANCHIFNOT; out_label lbl)
- | Pstring_test x =>
- (out_bool_test EQSTRING x; out BRANCHIF; out_label lbl)
- | Pnoteqtag_test tag =>
- (out BRANCHIFNEQTAG; out_tag tag; out_label lbl)
- ;
- emit C)
- | Kbranchinterval(low, high, lbl_low, lbl_high) :: C =>
- (out PUSH; out_int_const low; out PUSH;
- if low <> high then out_int_const high else ();
- out BRANCHINTERVAL;
- out_label lbl_low;
- out_label lbl_high;
- emit C)
- | Kprim Pidentity :: C =>
- emit C
- | Kprim p :: C =>
- (case p of
- Pdummy n =>
- (out DUMMY; out n)
- | Ptest tst =>
- (case tst of
- Peq_test => out EQ
- | Pnoteq_test => out NEQ
- | Pint_test tst => out_bool_test EQ tst
- | Pfloat_test tst => out_bool_test EQFLOAT tst
- | Pstring_test tst => out_bool_test EQSTRING tst
- | _ => fatalError "emit : Kprim, Ptest")
- | Patom t =>
- if t < 10 then out (ATOM0 + t) else (out ATOM; out t)
- | Pfield n =>
- if n < 4 then out (GETFIELD0 + n) else (out GETFIELD; out n)
- | Psetfield n =>
- if n < 4 then out (SETFIELD0 + n) else (out SETFIELD; out n)
- | Pccall(name, arity) =>
- (if arity <= 5 then
- out (C_CALL1 + arity - 1)
- else
- (out C_CALLN; out arity);
- slot_for_c_prim name)
- | Pfloatprim p =>
- (out FLOATOP;
- out(opcode_for_float_primitive p))
- | p =>
- out(opcode_for_primitive p)
- ;
- emit C)
- | Kpush :: Kget_global uid :: Kapply :: C =>
- (out PUSH_GETGLOBAL_APPLY;
- slot_for_get_global uid;
- emit C)
- | Kpush :: Kget_global uid :: Ktermapply :: C =>
- (out PUSH_GETGLOBAL_APPTERM;
- slot_for_get_global uid;
- emit C)
- | instr :: C =>
- (out (case instr of
- Kreturn => RETURN
- | Kgrab => GRAB
- | Kpush => PUSH
- | Kpushmark => PUSHMARK
- | Klet => LET
- | Kapply => APPLY
- | Ktermapply => APPTERM
- | Kpoptrap => POPTRAP
- | Kcheck_signals => CHECK_SIGNALS
- | _ => fatalError "emit: should not happen");
- emit C)
- ;
-